package com.yy.main.app;

import com.yy.constant.AppConstant;
import com.yy.main.app.service.IPermissionService;
import com.yy.main.app.springsession.SecurityInterceptor;
import com.yy.main.app.springsession.SessionInterceptor;
import net.bull.javamelody.MonitoringFilter;
import net.bull.javamelody.SessionListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.http.HttpSessionListener;

/**
 * <p>
 * spring boot核心启动类
 * </p>
 *
 * @author 杨阳
 * @since 2017年8月30日15:46:41
 */
//如果这是排除DataSourceAutoConfiguration的初始化，需要的mapper上显示的指定一个数据源，例如：@Resource(name = "dataSource")
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
//引入classpath下spring文件夹内的spring-开头的xml文件
@ImportResource(locations = {"classpath:spring/spring-*.xml"})
//@EnableSwagger2启动该注解使得用在controller中的swagger注解生效
@EnableSwagger2
@EnableFeignClients
@EnableDiscoveryClient
//启动断路器
@EnableHystrix
public class Application extends WebMvcConfigurerAdapter {

    @Resource(name = "iPermissionService")
    private IPermissionService iPermissionService;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    /**
     * <p>
     * 配置错误处理页面
     * </p>
     *
     * @return {@link EmbeddedServletContainerCustomizer}
     * @author 杨阳
     * @since 2017年12月4日
     */
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return configurableEmbeddedServletContainer -> {
            ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
            ErrorPage errorPage500 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/500");
            configurableEmbeddedServletContainer.addErrorPages(errorPage404);
            configurableEmbeddedServletContainer.addErrorPages(errorPage500);
        };
    }

    /**
     * <p>
     * 配置静态资源位置
     * </p>
     *
     * @param registry
     * @author 杨阳
     * @since 2017年11月13日
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (registry.hasMappingForPattern(AppConstant.WEB_JARS_PATTERN)) {
            registry.addResourceHandler(AppConstant.WEB_JARS_PATTERN)
                    .addResourceLocations(AppConstant.WEB_JARS_PATH);
        }
        if (!registry.hasMappingForPattern(AppConstant.LOCAL_STATIC_PATTERN)) {
            registry.addResourceHandler(AppConstant.LOCAL_STATIC_PATTERN).addResourceLocations(
                    AppConstant.LOCAL_STATIC_PATH);
        }
    }

    /**
     * <p>
     * 注册一个远程调用模板，主要负责文件上传，其它调用还是使用feign接口
     * </p>
     *
     * @return {@link RestTemplate}
     */
    @Bean(name = "restTemplate")
    //负载均衡
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * <p>
     * 增加session拦截器，判断用户是否登陆
     * </p>
     *
     * @author 杨阳
     * @since 2017年9月1日
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // session拦截器
        registry.addInterceptor(new SessionInterceptor()).addPathPatterns("/**");
        // 权限拦截器
        registry.addInterceptor(new SecurityInterceptor(iPermissionService)).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

    /**
     * <p>
     * javaMelody session监听
     * </p>
     *
     * @return {@link SessionListener}
     * @author 杨阳
     * @since 2017年9月4日
     */
    @Bean
    public HttpSessionListener javaMelodyListener() {
        return new net.bull.javamelody.SessionListener();
    }

    /**
     * <p>
     * javaMelody拦截器
     * </p>
     *
     * @return {@link MonitoringFilter}
     * @author 杨阳
     * @since 时间
     */
    @Bean
    public Filter javaMelodyFilter() {
        return new net.bull.javamelody.MonitoringFilter();
    }

}
